package com.mlh.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.injector.methods.SelectById;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mlh.entity.Category;
import com.mlh.service.CategoryService;
import com.mlh.util.RedisCache;
import com.mlh.vo.ArticleDetailVo;
import com.mlh.vo.ArticleListVo;
import com.mlh.vo.HotArticleVo;
import com.mlh.entity.Article;
import com.mlh.mapper.ArticleMapper;
import com.mlh.service.ArticleService;
import com.mlh.util.BeanCopyUtil;
import com.mlh.util.ResponseResult;

import com.mlh.vo.PageVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private RedisCache redisCache;

    @Override
    public ResponseResult hotArticleList() {
        //查询热门文章，返回浏览量前10的文章
        //是正式文章 浏览量降序  分页
        LambdaQueryWrapper<Article> wrapper=new LambdaQueryWrapper<>();
        //lambda表达式
        wrapper.eq(Article::getStatus,0);
        wrapper.orderByDesc(Article::getViewCount);
        //分页
        Page<Article> page = new Page<>(1,10);
        //这里的page()是ArticleServiceImpl实现IService<T> 接口的一个方法，不是我们上面定义的page
        page(page,wrapper);
        List<Article> records = page.getRecords();
        //不能直接用Article对象返回，Article对象包含了所有信息 包括重要 或者 与该接口调用无关的信息
        //利用Vo优化，返回需要的信息即可
        // List<HotArticleVo> hotArticleVoList=new ArrayList<>();
        // for (Article article : records) {
        //     HotArticleVo vo = new HotArticleVo();
        //     BeanUtils.copyProperties(article,vo);
        //     hotArticleVoList.add(vo);
        // }
        //上面代码通过自己写的BeanCopyUtil来完成
        List<HotArticleVo> hotArticleVoList = BeanCopyUtil.copyBeanList(records, HotArticleVo.class);
        return ResponseResult.okResult(hotArticleVoList);
    }

    @Override
    public ResponseResult articleList(Integer pageNum, Integer pageSize, Long categoryId) {
        //根据categoryId查询文章
        LambdaQueryWrapper<Article> lambdaQueryWrapper = new
                LambdaQueryWrapper<>();
        // 如果 categoryId不为null 那么查询的categoryId要与传入的categoryId相同
        //第一个参数是boolean类型，为true则需要进行值判断，否则直接跳过
        lambdaQueryWrapper.eq(Objects.nonNull(categoryId)&&categoryId>0
                ,Article::getCategoryId,categoryId);
        //置顶文章要在最前面  根据istop为1表示置顶，因此选用降序
        // 这里通过 Article::getIsTop 获取IsTop在表中的字段名  ???????????????????
        lambdaQueryWrapper.orderByDesc(Article::getIsTop);
        Page<Article> page=new Page<>(pageNum,pageSize);
        page(page,lambdaQueryWrapper);
        List<Article> records = page.getRecords();
        //查询categoryName
        for (Article article : records) {
            Category category = categoryService.getById(article.getCategoryId());
            article.setCategoryName(category.getName());
        }
        //这里是对上面的一个流式写法
        //article在前面没出现过，他是怎么被判断为Article类型的呢？
        // 是因为调用该方法的是stream流，stream 流中的对象是Article，这个本来就是给流进行类型映射
        //因此这里的article 就是Article对象，与变量名无关
        //利用这个写法 还需要在 Article类中增加 @Aeccssor 注解 让get方法能够返回实体类
        // articles.stream()
        //         .map(article ->
        //         article.setCategoryName(categoryService.getById(article.getCategoryId()).getName()))
        //         .collect(Collectors.toList());
        List<ArticleListVo> articleListVos = BeanCopyUtil.copyBeanList(records, ArticleListVo.class);
        //根据前端接口文档  需要传回 rows 还有total 因此定义一个PageVo来处理
        PageVo pageVo = new PageVo(articleListVos, page.getTotal());
        return ResponseResult.okResult(pageVo);
    }

    // 根据id返回文章的详细内容  并且 浏览量从redis读取
    @Override
    public ResponseResult getArticleDetail(Long id) {
        Article article = getById(id);
        //增加种类名
        Category category = categoryService.getById(article.getCategoryId());
        //防止空指针异常
        if(category!=null){
            article.setCategoryName(category.getName());
        }
        //添加浏览量信息
        //从redis中获取viewCount
        Integer viewCount = redisCache.getCacheMapValue("article:viewCount", id.toString());
        article.setViewCount(Long.valueOf(viewCount));
        return ResponseResult.okResult(BeanCopyUtil.copyBean(article, ArticleDetailVo.class));
    }

    //增加文章的阅读量
    @Override
    public ResponseResult updateViewCount(Long id) {
        //增加redis中的阅读量
        //这个方法我不知道  对redis api很不熟悉
        redisCache.incrementCacheMapValue("article:viewCount",id.toString(),1);
        return ResponseResult.okResult();
    }
}
